home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume17 / e2 / part02 < prev    next >
Encoding:
Internet Message Format  |  1989-02-08  |  30.8 KB

  1. Subject:  v17i096:  E, friendlier front-end to vi, Part02/03
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: speedboat jones <tcjones@watdragon.waterloo.edu>
  7. Posting-number: Volume 17, Issue 96
  8. Archive-name: e2/part02
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 2 (of 3)."
  17. # Contents:  MODS ask_hist.c dir_find.c e.h main.c multiple.c
  18. #   spell_help.c terminal.c
  19. # Wrapped by tcjones@watdragon on Thu Feb  9 10:01:02 1989
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'MODS' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'MODS'\"
  23. else
  24. echo shar: Extracting \"'MODS'\" \(2757 characters\)
  25. sed "s/^X//" >'MODS' <<'END_OF_FILE'
  26. e Modification History.
  27. X=======================
  28. X
  29. X
  30. Version 1.1 changes          October 1987.
  31. X==========================================
  32. X- Added "VIPATH" environment variable.
  33. X- Fixed bug with argument lists that exceeded ARG_CHARS chars in multiple().
  34. X- Added #ifdef statements to enable compilation on a SUN.
  35. X- Put #defines etc into e.h as they were getting in the way.
  36. X
  37. X
  38. Version 1.2 changes          December 1987.
  39. X===========================================
  40. X- Made the numbering on "e -" the same as for "e .".
  41. X- System V port (thanks to Simon Brown).
  42. X- Added man page (thanks to Phil Oldiges).
  43. X- Fixed handling of the VIPATH variable so that it doesn't screw up
  44. X    when there is more than one delimiter. Added new delimiters.
  45. X- Cleaned up terminal handling to use ioctl().
  46. X- Cleaned up error handling.
  47. X- Fixed (for sure this time) the bug with long argument lists.
  48. X- Made returns consistent in check().
  49. X- Flagged suspected unsatisfied symbolic link in check().
  50. X- Added #define called E_PATH which contains the name of the environment
  51. X    variable containing the PATH for cross directory stuff. (set to "VIPATH").
  52. X- Added E_MODE #define for the protection mode for .e (set to 0644).
  53. X- Fixed spelling correction to offer all likely targets in a directory, not
  54. X    just the first encountered. Added 'N' option to say "I meant what I said,
  55. X    don't give me more possible corrections."
  56. X- Comments!
  57. X
  58. Version 1.3 changes         December 1988.
  59. X==========================================
  60. X
  61. X- Fixed error message when unable to open E_PATH component directory.
  62. X- Added N option to cross-directory suggestions (==> no more suggestions)
  63. X    should have done this in 1.2.
  64. X- Made centralised .e file in the home directory.
  65. X- Split source into twenty odd files.
  66. X- Rewrote e.h to make it more manageable.
  67. X- Rewrote Makefile.
  68. X- Added E_HIST (set to "VIHIST") getenv to let the user decide where the
  69. X    history should live & what to call it. Defaults to $HOME/.e
  70. X- Added E_INHERIT and E_SAFE_INHERIT (set to "VIINHERIT" and "VISAFEINHERIT")
  71. X    to allow/disable inheritance of .exrc files in other directories. See the
  72. X    man page for details.
  73. X
  74. To be added?
  75. X============
  76. X
  77. X- Allow backspacing on a select line.
  78. X- Spelling corrections across directories.
  79. X- Plenty of fancy things.
  80. X
  81. X
  82. X
  83. X-------------------------------------------------------------------------------
  84. Terry Jones, Department Of Computer Science, University Of Waterloo
  85. X             Waterloo Ontario Canada N2L 3G1
  86. X
  87. X{ihnp4,allegra,decvax,utzoo,utcsri,clyde}!watmath!watdragon!tcjones
  88. tcjones@dragon.waterloo.{cdn,edu} tcjones@WATER.bitnet
  89. tcjones%watdragon@waterloo.csnet [from oz, tcjones@dragon.waterloo.cdn@munnari]
  90. X-------------------------------------------------------------------------------
  91. END_OF_FILE
  92. if test 2757 -ne `wc -c <'MODS'`; then
  93.     echo shar: \"'MODS'\" unpacked with wrong size!
  94. fi
  95. chmod +x 'MODS'
  96. # end of 'MODS'
  97. fi
  98. if test -f 'ask_hist.c' -a "${1}" != "-c" ; then 
  99.   echo shar: Will not clobber existing file \"'ask_hist.c'\"
  100. else
  101. echo shar: Extracting \"'ask_hist.c'\" \(2657 characters\)
  102. sed "s/^X//" >'ask_hist.c' <<'END_OF_FILE'
  103. X#include "e.h"
  104. X
  105. X
  106. X/*
  107. X * Question the user about which file from the history is wanted.
  108. X *
  109. X */
  110. void
  111. ask_hist()
  112. X{
  113. X    register int i;
  114. X    register int option;
  115. X
  116. X    /* Print the history. */
  117. X    for (i = 0; i < hist_count; i++){
  118. X        ok_fprintf(stderr, "\t[%d]: %s\n", hist_count-i-1, hist[i]);
  119. X    }
  120. X
  121. X    option = char_in("select -> ");
  122. X
  123. X    /* 
  124. X     * Process the option and put the appropriate file name into the 
  125. X     * arg variable.
  126. X     *
  127. X     */
  128. X
  129. X    if (option == '\n'){
  130. X        /* 
  131. X         * They want the last file of the list. 
  132. X         * There's no need to reconstruct, the history is already correct.
  133. X         *
  134. X         */
  135. X        ok_fprintf(stderr, "%s\n", hist[hist_count - 1]);
  136. X        ok_sprintf(arg, "%s", hist[hist_count - 1]);
  137. X        abandon();
  138. X        return;
  139. X    }
  140. X    else if (option == (int)erase){
  141. X        /* 
  142. X         * They want to leave. 
  143. X         *
  144. X         */
  145. X        ok_fprintf(stderr, "\n");
  146. X        abandon();
  147. X        exit(1);
  148. X    }
  149. X    else if (option >= '0' && option <= '0' + hist_count - 1){
  150. X        /* 
  151. X         * They have requested a file by its history number. 
  152. X         *
  153. X         */
  154. X        register int want = hist_count - (option - '0') - 1;
  155. X        ok_fprintf(stderr, "%s\n", hist[want]);
  156. X        ok_sprintf(arg, "%s", hist[want]);
  157. X        reconstruct(want);
  158. X        return;
  159. X    }
  160. X    else{
  161. X        /* 
  162. X         * Looks like they want to name a specific file. Echo the 
  163. X         * character back to the screen. Then get the rest of the filename.
  164. X         *
  165. X         */
  166. X        ok_fprintf(stderr, "%c", option);
  167. X        arg[0] = (char)option;
  168. X        i = 1;
  169. X        while ((arg[i] = (char)getc(stdin)) != '\n'){
  170. X            i++;
  171. X        }
  172. X        arg[i] = '\0';
  173. X
  174. X        /* 
  175. X         * Seeing as they typed in the name, try and help with spelling. 
  176. X         * If you can't help with spelling, see if there is a file in a
  177. X         * directory mentioned in the VIPATH list that might have been the
  178. X         * file that was meant.
  179. X         *
  180. X         */
  181. X        if (!spell_help(0)){
  182. X            dir_find();
  183. X        }
  184. X
  185. X        /* 
  186. X         * If it is in the history then reconstruct and return. 
  187. X         *
  188. X         */
  189. X        for (i = 0; i < hist_count; i++){
  190. X            if (!strcmp(hist[i], arg)){
  191. X                reconstruct(i);
  192. X                return;
  193. X            }
  194. X        }
  195. X
  196. X        /* 
  197. X         * Otherwise reconstruct, leaving out the oldest name if needed.
  198. X         * reconstruct(-1) will exclude nothing - the history is not full.
  199. X         *
  200. X         */
  201. X        if (hist_count == HIST_LINES){
  202. X            reconstruct(0);
  203. X        }
  204. X        else{
  205. X            reconstruct(-1);
  206. X        }
  207. X    }
  208. X    return;
  209. X}
  210. END_OF_FILE
  211. if test 2657 -ne `wc -c <'ask_hist.c'`; then
  212.     echo shar: \"'ask_hist.c'\" unpacked with wrong size!
  213. fi
  214. # end of 'ask_hist.c'
  215. fi
  216. if test -f 'dir_find.c' -a "${1}" != "-c" ; then 
  217.   echo shar: Will not clobber existing file \"'dir_find.c'\"
  218. else
  219. echo shar: Extracting \"'dir_find.c'\" \(3846 characters\)
  220. sed "s/^X//" >'dir_find.c' <<'END_OF_FILE'
  221. X#include "e.h"
  222. X#include "dir_find.h"
  223. X
  224. X/*
  225. X * dir_find()
  226. X *
  227. X * This takes the environment variable which is #defined as PATH and 
  228. X * extracts the directory names from it. They may be separated by 
  229. X * arbitrary numbers of delimiter characters (currently "\n", "\t", " " 
  230. X * and ":"). Each directory is then checked to see if it contains the 
  231. X * desired filename (with a call to check). Spelling corrections are 
  232. X * not attempted.
  233. X *
  234. X * This could have been done more simply using strtok() but I didn't know
  235. X * about that then... You'll have to bear with me.
  236. X *
  237. X * 'this_dir' will point at the start of the directory name that is to be
  238. X * processed. 'cp' will be advanced to the next delimiter which will be zeroed
  239. X * and then 'cp' will be again advanced until it reaches a non-delimiter. This
  240. X * marks the start of the next name and at the bottom of the loop 'this_dir'
  241. X * is set to be 'cp' and we begin again.
  242. X *
  243. X * skip_delim() and friends are macros that live in dir_find.h
  244. X *
  245. X */
  246. void
  247. dir_find()
  248. X{
  249. X    char *p;
  250. X    char path[E_PATH_LEN];
  251. X    char *this_dir;
  252. X    char *cp;
  253. X
  254. X    /*
  255. X     * Get the environment variable, check its length and cp it to a safe spot.
  256. X     *
  257. X     */
  258. X    p = getenv(E_PATH);
  259. X    if (!p) return;
  260. X
  261. X    if (strlen(p) >= E_PATH_LEN){
  262. X        e_error("Length of '%s' variable exceeds %d.", E_PATH, MAXPATHLEN);
  263. X    }
  264. X
  265. X    strcpy(path, p);
  266. X
  267. X    /*
  268. X     * Begin at the beginning...
  269. X     *
  270. X     */
  271. X    cp = path;
  272. X    skip_delim(cp);
  273. X
  274. X    if (!*cp){
  275. X        /* 
  276. X         * There was nothing there but delimiters! 
  277. X         *
  278. X         */
  279. X        return;
  280. X    }
  281. X
  282. X    this_dir = cp;
  283. X
  284. X    while (*this_dir){
  285. X
  286. X        /* 
  287. X         * Move "cp" along to the first delimiter. 
  288. X         *
  289. X         */
  290. X        skip_to_next_delim(cp);
  291. X
  292. X        /*
  293. X         * If it's not already '\0' then zero it and move on. Otherwise we
  294. X         * have reached the end of the string.
  295. X         *
  296. X         */
  297. X        if (*cp){
  298. X            *cp = '\0';
  299. X            cp++;
  300. X        }
  301. X
  302. X        /* 
  303. X         * Move "cp" along over delimiters unitl the next directory name. 
  304. X         *
  305. X         */
  306. X        skip_delim(cp);
  307. X
  308. X        /* 
  309. X         * Check the directory "this_dir" for the filename "arg". 
  310. X         * If it's there, offer it to them.
  311. X         *
  312. X         */
  313. X        if (dir_check(arg, this_dir)){
  314. X
  315. X            char prompt[MAXPATHLEN + 128];
  316. X            ok_sprintf(prompt, "%s/%s [y]? ", this_dir, arg);
  317. X
  318. X            /* 
  319. X             * Get and process the reply. 
  320. X             *
  321. X             */
  322. X            switch (char_in(prompt)){
  323. X
  324. X                case 'N':{
  325. X                    /*
  326. X                     * They don't want it and they don't want more help.
  327. X                     *
  328. X                     */
  329. X                    ok_fprintf(stderr, "No!\n");
  330. X                    return;
  331. X                }
  332. X
  333. X                case 'n':{
  334. X                    /*
  335. X                     * They don't want it but continue to search for another.
  336. X                     *
  337. X                     */
  338. X                    ok_fprintf(stderr, "no\n");
  339. X                    break;
  340. X                }
  341. X
  342. X                case 'q':
  343. X                case 'Q':{
  344. X                    /*
  345. X                     * Get out.
  346. X                     *
  347. X                     */
  348. X                    ok_fprintf(stderr, "quit\n");
  349. X                    abandon();
  350. X                    exit(0);
  351. X                }
  352. X
  353. X                default :{
  354. X                    /*
  355. X                     * They want it. Set up the filename in 'arg'.
  356. X                     *
  357. X                     */
  358. X                    char tmp[MAXPATHLEN];
  359. X
  360. X                    ok_fprintf(stderr, "yes\n");
  361. X                    ok_sprintf(tmp, "%s/%s", this_dir, arg);
  362. X                    arg[0] = '\0';
  363. X                    strcat(arg, tmp);
  364. X                    return;
  365. X                }
  366. X            }
  367. X        }
  368. X        this_dir = cp;
  369. X    }
  370. X
  371. X    return;
  372. X}
  373. END_OF_FILE
  374. if test 3846 -ne `wc -c <'dir_find.c'`; then
  375.     echo shar: \"'dir_find.c'\" unpacked with wrong size!
  376. fi
  377. # end of 'dir_find.c'
  378. fi
  379. if test -f 'e.h' -a "${1}" != "-c" ; then 
  380.   echo shar: Will not clobber existing file \"'e.h'\"
  381. else
  382. echo shar: Extracting \"'e.h'\" \(4788 characters\)
  383. sed "s/^X//" >'e.h' <<'END_OF_FILE'
  384. X/*
  385. X * e.h 
  386. X * version 1.3
  387. X *
  388. X * Terry Jones, Department of Computer Science, University of Waterloo
  389. X *              Waterloo Ontario Canada N2L 3G1
  390. X * {ihnp4,allegra,decvax,utzoo,utcsri,clyde}!watmath!watdragon!tcjones
  391. X * tcjones@dragon.waterloo.{cdn,edu} tcjones@WATER.bitnet
  392. X * tcjones%watdragon@waterloo.csnet 
  393. X *
  394. X */
  395. X
  396. X
  397. X#ifdef Bsd
  398. X#   include <stdio.h>
  399. X#   include <sys/types.h>
  400. X#   include <sys/stat.h>
  401. X#   include <signal.h>
  402. X#   include <sys/param.h>
  403. X#   include <pwd.h>
  404. X#   include <ctype.h>
  405. X#   include <sysexits.h>
  406. X#   include <sys/file.h>
  407. X#   include <sys/dir.h>
  408. X#   include <strings.h>
  409. X#   include <sys/ioctl.h>
  410. X#   define VI "/usr/ucb/vi"
  411. X    uid_t getuid();
  412. X    uid_t getgid();
  413. X#endif /* Bsd */
  414. X
  415. X
  416. X#ifdef Sun
  417. X#   include <stdio.h>
  418. X#   include <sys/types.h>
  419. X#   include <sys/stat.h>
  420. X#   include <signal.h>
  421. X#   include <sys/param.h>
  422. X#   include <pwd.h>
  423. X#   include <ctype.h>
  424. X#   include <sysexits.h>
  425. X#   include <sys/file.h>
  426. X#   include <sys/dir.h>
  427. X#   include <strings.h>
  428. X#   include <sys/time.h>
  429. X#   include <sys/vnode.h>
  430. X#   include <ufs/inode.h>
  431. X#   include <sgtty.h>
  432. X#   define VI "/usr/ucb/vi"
  433. X    extern char *sprintf();
  434. X#endif /* Sun */
  435. X
  436. X
  437. X#ifdef Sysv
  438. X#   include <stdio.h>
  439. X#   include <sys/types.h>
  440. X#   include <sys/stat.h>
  441. X#   include <signal.h>
  442. X#   include <sys/param.h>
  443. X#   include <pwd.h>
  444. X#   include <ctype.h>
  445. X#   include <sys/file.h>
  446. X#   include <termio.h>
  447. X#   include <string.h>
  448. X#   include <fcntl.h>
  449. X#   include <dirent.h>
  450. X#   include <sys/dir.h>
  451. X#   define index strchr
  452. X#   define rindex strrchr
  453. X#   define direct dirent
  454. X#   define MAXPATHLEN MAXNAMLEN
  455. X#   define ok_sprintf sprintf
  456. X#   define VI "/usr/bin/vi"
  457. X    extern struct passwd *getpwuid();
  458. X#endif /* Sysv */
  459. X
  460. X
  461. X#ifdef Ultrix
  462. X#   include <stdio.h>
  463. X#   include <sys/types.h>
  464. X#   include <sys/stat.h>
  465. X#   include <signal.h>
  466. X#   include <sys/param.h>
  467. X#   include <pwd.h>
  468. X#   include <ctype.h>
  469. X#   include <sysexits.h>
  470. X#   include <sys/file.h>
  471. X#   include <sys/dir.h>
  472. X#   include <strings.h>
  473. X#   include <sys/ioctl.h>
  474. X#   define VI "/usr/ucb/vi"
  475. X#endif /* Ultrix */
  476. X
  477. X
  478. X#ifdef Dynix
  479. X#   include <stdio.h>
  480. X#   include <sys/types.h>
  481. X#   include <sys/stat.h>
  482. X#   include <signal.h>
  483. X#   include <sys/param.h>
  484. X#   include <pwd.h>
  485. X#   include <ctype.h>
  486. X#   include <sys/dir.h>
  487. X#   include <sys/ioctl.h>
  488. X#   include <strings.h>
  489. X#   define VI "/usr/ucb/vi"
  490. X#endif /* Dynix */
  491. X
  492. X#ifdef waterloo
  493. X#   include <stdlib.h>
  494. X#endif
  495. X
  496. X/*
  497. X * Other checks...
  498. X *
  499. X */
  500. X
  501. X#ifndef IREAD
  502. X#   define IREAD    0400
  503. X#endif
  504. X
  505. X#ifndef EX_IOERR
  506. X#   define EX_IOERR 1
  507. X#endif
  508. X
  509. X
  510. X/*
  511. X * Things that aren't portability concerns.
  512. X *
  513. X */
  514. X
  515. X#define DEFAULT_HIST    ".e"
  516. X#define HIST_LINES      9
  517. X#define HIST_CHARS      1024
  518. X#define E_PATH          "VIPATH"
  519. X#define E_HIST          "VIHIST"
  520. X#define E_INHERIT       "VIINHERIT"
  521. X#define E_SAFE_INHERIT  "VISAFEINHERIT"
  522. X#define E_PATH_LEN      2048
  523. X#define ARG_CHARS       4096
  524. X#define MAX_ARGS        100
  525. X#define O_READ          00004
  526. X#define G_READ          0004
  527. X#define TERM_RECORD     0
  528. X#define TERM_SET        1
  529. X#define TERM_RESET      2
  530. X#define VERSION         "1.3"
  531. X
  532. X/*
  533. X * STRUCT_ASST should be defined if your cc can handle structural assignments. 
  534. X *
  535. X * This is only used in the function terminal(). Leave STRUCT_ASST
  536. X * defined and if it doesn't break you're ok. If it does, undefine it and
  537. X * you'll definitely be ok (but things will run slower - even though you
  538. X * wont notice it.) Words words words. Ho hum.
  539. X *
  540. X */
  541. X
  542. X#define STRUCT_ASST
  543. X
  544. X
  545. int char_in();
  546. int check();
  547. int clean_up();
  548. int dir_check();
  549. int match();
  550. int read_hist();
  551. int safety_first();
  552. int sp_dist();
  553. int spell_help();
  554. void abandon();
  555. void ask_hist();
  556. void catch_signals();
  557. void check_hist();
  558. void dir_find();
  559. void do_vi();
  560. void e();
  561. void e_error();
  562. void find();
  563. void find_hist();
  564. void find_match();
  565. void get_temp();
  566. void inheritance();
  567. void insert_cmd();
  568. void multiple();
  569. void new_vi();
  570. void normal();
  571. void nth_hist();
  572. void ok_fprintf();
  573. void ok_sprintf();
  574. void reconstruct();
  575. void terminal();
  576. X
  577. X
  578. extern char *getenv();
  579. extern char *mktemp();
  580. extern char *sbrk();
  581. X#ifndef Sysv
  582. X    extern char *getwd();
  583. X    void ok_sprintf();
  584. X#endif
  585. X
  586. extern FILE *hist_fp;
  587. extern FILE *tmp_fp;
  588. extern char *hist[];
  589. extern char *home;
  590. extern char *myname;
  591. extern char *saved_line;
  592. extern char arg[];
  593. extern char cwd[];
  594. extern char ehist[];
  595. extern char erase;
  596. extern char tmp_file[];
  597. extern int emode;
  598. extern int hist_count;
  599. extern int inherit;
  600. extern int safe_inherit;
  601. extern int uid;
  602. X
  603. X
  604. X/* 
  605. X * Walk over white space. 
  606. X *
  607. X */
  608. X#define skip_white(c) while (*(c) == ' ' || *(c) == '\t') (c)++;
  609. X
  610. X/* 
  611. X * Walk over non-white characters. 
  612. X *
  613. X */
  614. X#define skip_to_white(c) while (*(c) && *(c) != ' ' && *(c) != '\t') (c)++;
  615. X
  616. X/* 
  617. X * Run down a string and zap the newline if we find one. 
  618. X *
  619. X */
  620. X#define zap_nl(c) while (*(c) && *(c) != '\n') (c)++; *(c) = '\0';
  621. END_OF_FILE
  622. if test 4788 -ne `wc -c <'e.h'`; then
  623.     echo shar: \"'e.h'\" unpacked with wrong size!
  624. fi
  625. chmod +x 'e.h'
  626. # end of 'e.h'
  627. fi
  628. if test -f 'main.c' -a "${1}" != "-c" ; then 
  629.   echo shar: Will not clobber existing file \"'main.c'\"
  630. else
  631. echo shar: Extracting \"'main.c'\" \(2804 characters\)
  632. sed "s/^X//" >'main.c' <<'END_OF_FILE'
  633. X
  634. X/*******************************************************************************
  635. X#  E - command line preprocessor for vi.  Version 1.3 - November 1988.         #
  636. X#  ===================================================================         #
  637. X#                                                                              #
  638. X#  Terry Jones, Department of Computer Science, University of Waterloo         #
  639. X#  Waterloo, Ontario, Canada. N2L 3G1                                          #
  640. X#                                                                              #
  641. X#  {ihnp4,allegra,decvax,utzoo,utcsri,clyde}!watmath!watdragon!tcjones         #
  642. X#  tcjones@dragon.waterloo.{cdn,edu} tcjones@WATER.bitnet                      #
  643. X#  tcjones%watdragon@waterloo.csnet                                            #
  644. X*******************************************************************************/
  645. X
  646. X
  647. X#include "e.h"
  648. X
  649. XFILE *hist_fp = NULL;        /* The original .e file                        */
  650. XFILE *tmp_fp = NULL;         /* The new .e file                             */
  651. char *hist[HIST_LINES];      /* Pointers to history items.                  */
  652. char *home;                  /* Home directory.                             */
  653. char *myname;                /* argv[0]                                     */
  654. char *saved_line = NULL;     /* In case we read one line too many later on. */
  655. char arg[ARG_CHARS];         /* The arguments that vi will be invoked with. */
  656. char cwd[MAXPATHLEN];        /* The directory from which we're invoked.     */
  657. char ehist[MAXPATHLEN];      /* The name of the original .e file.           */
  658. char erase;                  /* The terminal's erase character.             */
  659. char tmp_file[MAXPATHLEN];   /* The name of the new .e file.                */
  660. int emode;                   /* The protection mode of the original .e.     */
  661. int hist_count;              /* The # of items in the history for this dir. */
  662. int safe_inherit = 0;        /* Never inherit other people's .exrc's        */
  663. int inherit = 0;             /* Inherit .exrc files?                        */
  664. int uid;                     /* The user's uid.                             */
  665. X
  666. X
  667. main(argc, argv)
  668. int argc;
  669. char **argv;
  670. X{
  671. X    /*
  672. X     * Do some preliminary things. Grab the name we were invoked with,
  673. X     * record the status of the terminal so we can restore it later if
  674. X     * we have to alter it for some reason, arrange to catch SIGINT and
  675. X     * read and split up the history for this directory.
  676. X     *
  677. X     * Then call e which handles the arguments and calls other things
  678. X     * to get the job done. e should never return.
  679. X     */
  680. X
  681. X    myname = argv[0];
  682. X    terminal(TERM_RECORD);
  683. X    catch_signals();
  684. X    inheritance();
  685. X    find_hist();
  686. X    hist_count = read_hist();
  687. X    e(argc, argv);
  688. X    return 1;
  689. X}
  690. END_OF_FILE
  691. if test 2804 -ne `wc -c <'main.c'`; then
  692.     echo shar: \"'main.c'\" unpacked with wrong size!
  693. fi
  694. chmod +x 'main.c'
  695. # end of 'main.c'
  696. fi
  697. if test -f 'multiple.c' -a "${1}" != "-c" ; then 
  698.   echo shar: Will not clobber existing file \"'multiple.c'\"
  699. else
  700. echo shar: Extracting \"'multiple.c'\" \(2638 characters\)
  701. sed "s/^X//" >'multiple.c' <<'END_OF_FILE'
  702. X#include "e.h"
  703. X
  704. X/*
  705. X * There were several names on the command line, so we just strcat them
  706. X * into the 'arg' array. Check to see that the length of all the args
  707. X * will not be greater than "size" or else we will overflow arg.
  708. X *
  709. X * This is actually insane - we put the args into a char array to pass to
  710. X * do_vi, and then it promptly sticks them back into a char ** arrangement.
  711. X * Ugh.
  712. X *
  713. X * The total argument length must be at most size - 1 characters, including
  714. X * spaces. arg needs to have a trailing '\0' so that do_vi() wont break.
  715. X *
  716. X */
  717. X
  718. void
  719. multiple(number, args, size)
  720. int number;
  721. char **args;
  722. int size;
  723. X{
  724. X    register i;
  725. X    register total = 0;
  726. X    char temp_arg[ARG_CHARS];
  727. X
  728. X    temp_arg[0] = '\0';
  729. X    while (--number){
  730. X        if ((total += strlen(*(args + 1))) >= size){
  731. X
  732. X            /*
  733. X             * If you are running e and you find that this condition occurs,
  734. X             * the solution is to simply increase the value of the #define
  735. X             * line for ARG_CHARS in e.h. It shouldn't happen under normal
  736. X             * circumstances.
  737. X             *
  738. X             */
  739. X
  740. X            ok_fprintf(stderr,
  741. X                "\007Argument list too long, truncated after '%s'.\n", *args);
  742. X            sleep(2);   /* Give them some chance to see what happened. */
  743. X            break;
  744. X        }
  745. X
  746. X        arg[0] = '\0';
  747. X        strcat(arg, *++args);
  748. X        (void) spell_help(1);
  749. X        strcat(temp_arg, arg);
  750. X        strcat(temp_arg, " ");
  751. X
  752. X        if (number > 1){
  753. X            strcat(arg, " ");
  754. X
  755. X            /* 
  756. X             * Add one to total for the space. There's no need to check for
  757. X             * overflow here as we know there is another argument since
  758. X             * number > 1 still. Thus if this overflows arg, then it is going
  759. X             * to be caught anyway in the test at the top of the while loop.
  760. X             *
  761. X             */
  762. X
  763. X            total++;                
  764. X        }
  765. X    }
  766. X
  767. X    strcpy(arg, temp_arg);
  768. X
  769. X    /*
  770. X     * Now, if there is a history file and we can find an identical line
  771. X     * then reconstruct with that line at the bottom.
  772. X     *
  773. X     */
  774. X
  775. X    if (hist_count != -1){
  776. X        for (i = 0; i < hist_count; i++){
  777. X            if (!strcmp(hist[i], arg)){
  778. X                reconstruct(i);
  779. X                return;
  780. X            }
  781. X        }
  782. X
  783. X        /*
  784. X         * Reconstruct and leave out the oldest if needed.
  785. X         *
  786. X         */
  787. X        if (hist_count == HIST_LINES){
  788. X            reconstruct(0);
  789. X        }
  790. X        else{
  791. X            reconstruct(-1);
  792. X        }
  793. X    }
  794. X    else{
  795. X        /* There was no history file so try to give them one for next time. */
  796. X        new_vi();
  797. X    }
  798. X    return;
  799. X}
  800. END_OF_FILE
  801. if test 2638 -ne `wc -c <'multiple.c'`; then
  802.     echo shar: \"'multiple.c'\" unpacked with wrong size!
  803. fi
  804. # end of 'multiple.c'
  805. fi
  806. if test -f 'spell_help.c' -a "${1}" != "-c" ; then 
  807.   echo shar: Will not clobber existing file \"'spell_help.c'\"
  808. else
  809. echo shar: Extracting \"'spell_help.c'\" \(3614 characters\)
  810. sed "s/^X//" >'spell_help.c' <<'END_OF_FILE'
  811. X#include "e.h"
  812. X
  813. X/*
  814. X * spell_help()
  815. X *
  816. X * Read the directory and if the file they want (in 'arg') does not
  817. X * exist then see if there is one that does which has similar spelling
  818. X * to what they requested. Offer the change and handle the reply.
  819. X *
  820. X * The argument tells us how we should form the prompt if we get a match.
  821. X * 1 = this file was one of several arguments to e and so we should say
  822. X * "correct 'frde' to 'fred'?". If there were only one argument it would
  823. X * be redundant to say that, they know their argument was 'frde', so we
  824. X * just say "correct to 'frde'?". Little things make all the difference.
  825. X *
  826. X * Return 1 if we were able to help, 0 otherwise.
  827. X *
  828. X */
  829. int
  830. spell_help(flag)
  831. int flag;
  832. X{
  833. X    DIR *dp; 
  834. X    DIR *opendir();
  835. X    struct direct *readdir();
  836. X    struct direct *entry;
  837. X    register int len = strlen(arg);
  838. X    struct stat buf;
  839. X    int ch;
  840. X
  841. X    /* 
  842. X     * If the file already exists just return - they don't need help. 
  843. X     *
  844. X     */
  845. X    if (stat(arg, &buf) == 0){
  846. X        return 1;
  847. X    }
  848. X
  849. X    /* 
  850. X     * If the current directory can't be read then return. 
  851. X     *
  852. X     */
  853. X    if ((dp = opendir(".")) == NULL){
  854. X        return 0;
  855. X    }
  856. X
  857. X    for (entry = readdir(dp); entry != NULL; entry = readdir(dp)){
  858. X
  859. X#ifdef Sysv
  860. X        register int dlen = strlen(entry->d_name);
  861. X#else
  862. X        register int dlen = entry->d_namlen;
  863. X#endif
  864. X
  865. X        if (stat(entry->d_name, &buf) == -1){
  866. X            continue;
  867. X        }
  868. X
  869. X        /* 
  870. X         * If it's not a regular file then continue. 
  871. X         *
  872. X         */
  873. X        if ((buf.st_mode&S_IFMT) != S_IFREG){
  874. X            continue;
  875. X        }
  876. X
  877. X        /* 
  878. X         * If this entry has a non-zero inode number and
  879. X         *
  880. X         *      name length == sought length +/- 1 
  881. X         *
  882. X         * then it should be checked.
  883. X         *
  884. X         */
  885. X
  886. X        if (entry->d_ino && dlen >= len - 1 && dlen <= len + 1){
  887. X
  888. X            char prompt[MAXPATHLEN + 128];
  889. X
  890. X            /* 
  891. X             * If the distance between this name and the one the user enetered
  892. X             * is too great then just continue.
  893. X             *
  894. X             */
  895. X
  896. X            if (sp_dist(entry->d_name, arg) == 3) continue;
  897. X
  898. X
  899. X            /* 
  900. X             * Otherwise offer them this one and get the response.
  901. X             *
  902. X             */
  903. X            if (flag){
  904. X                ok_sprintf(prompt, "correct '%s' to '%s' [y]? ", arg, 
  905. X                    entry->d_name);
  906. X            }
  907. X            else{
  908. X                ok_sprintf(prompt, "correct to '%s' [y]? ", entry->d_name);
  909. X            }
  910. X            ch = char_in(prompt);
  911. X
  912. X            if (ch == 'N'){
  913. X                /* 
  914. X                 * No, and they mean it. Offer no more help. 
  915. X                 *
  916. X                 */
  917. X                ok_fprintf(stderr, "No!\n");
  918. X                break;
  919. X            }
  920. X
  921. X            else if (ch == 'n'){
  922. X                /* 
  923. X                 * No, but they'd like more help. 
  924. X                 *
  925. X                 */
  926. X                ok_fprintf(stderr, "no\n");
  927. X                continue;
  928. X            }
  929. X
  930. X            else if (ch == 'q' || ch == 'Q' || ch == (int)erase){
  931. X                /* 
  932. X                 * Quit. 
  933. X                 *
  934. X                 */
  935. X                ok_fprintf(stderr, "quit\n");
  936. X                closedir(dp);
  937. X                abandon();
  938. X                exit(0);
  939. X            }
  940. X
  941. X            else{
  942. X                /* 
  943. X                 * Yes. 
  944. X                 *
  945. X                 */
  946. X                ok_fprintf(stderr, "yes\n");
  947. X                closedir(dp);
  948. X                strcpy(arg, entry->d_name);
  949. X                return 1;
  950. X            }
  951. X        }
  952. X    }
  953. X    closedir(dp);
  954. X    return 0;
  955. X}
  956. END_OF_FILE
  957. if test 3614 -ne `wc -c <'spell_help.c'`; then
  958.     echo shar: \"'spell_help.c'\" unpacked with wrong size!
  959. fi
  960. # end of 'spell_help.c'
  961. fi
  962. if test -f 'terminal.c' -a "${1}" != "-c" ; then 
  963.   echo shar: Will not clobber existing file \"'terminal.c'\"
  964. else
  965. echo shar: Extracting \"'terminal.c'\" \(3469 characters\)
  966. sed "s/^X//" >'terminal.c' <<'END_OF_FILE'
  967. X#include "e.h"
  968. X
  969. X/*
  970. X * terminal()
  971. X *
  972. X * Handles the terminal. Must be first called as terminal(TERM_RECORD)
  973. X * which remembers the initial terminal charcteristics and sets up the
  974. X * "erase" variable. Thereafter can be called either as
  975. X *
  976. X * terminal(TERM_SET)  --  to turn on CBREAK and ECHO off.
  977. X * terminal(TERM_RESET)  --  to set the terminal to its original state.
  978. X *
  979. X * This code is definitely a mess. If you don't have Sysv defined it does 
  980. X * things which are known to work for BSD, SUN, ULTRIX and DYNIX.
  981. X *
  982. X */
  983. void
  984. terminal(what)
  985. int what;
  986. X{
  987. X#ifdef Sysv
  988. X    static struct termio initial_blk;
  989. X    static struct termio set_blk;
  990. X#else
  991. X    static struct sgttyb initial_blk;
  992. X    static struct sgttyb set_blk;
  993. X#endif /* Sysv */
  994. X
  995. X
  996. X
  997. X    switch(what){
  998. X
  999. X        case TERM_RECORD:{
  1000. X#ifdef Sysv
  1001. X            if (ioctl(0, TCGETA, (char *)&initial_blk) == -1){
  1002. X                e_error("Could not ioctl stdin.");
  1003. X            }
  1004. X
  1005. X#ifdef STRUCT_ASST
  1006. X            /* Copy the structure in one hit. */
  1007. X            set_blk = initial_blk;
  1008. X#else
  1009. X            /* Copy the structure field by field. */
  1010. X            set_blk.c_iflag = initial_blk.c_iflag;
  1011. X            set_blk.c_oflag = initial_blk.c_oflag;
  1012. X            set_blk.c_cflag = initial_blk.c_cflag;
  1013. X            set_blk.c_line = initial_blk.c_line;
  1014. X
  1015. X            for (i = 0; i < NCC; i++){
  1016. X                set_blk.c_cc[i] = initial_blk.c_cc[i];
  1017. X            }
  1018. X#endif /* STRUCT_ASST */
  1019. X
  1020. X            /* And now set up the set_blk. */
  1021. X            set_blk.c_lflag = (initial_blk.c_lflag &= ~(ICANON|ECHO|ECHONL));
  1022. X            set_blk.c_lflag &= ICANON;
  1023. X            erase = set_blk.c_cc[VERASE];
  1024. X            set_blk.c_cc[VMIN] = 1;
  1025. X            set_blk.c_cc[VTIME] = 0;
  1026. X#else
  1027. X            if (ioctl(0, TIOCGETP, (char *)&initial_blk) == -1){
  1028. X                e_error("Could not ioctl stdin.");
  1029. X            }
  1030. X
  1031. X#ifdef STRUCT_ASST
  1032. X            /* Copy the structure in one hit. */
  1033. X            set_blk = initial_blk;
  1034. X#else
  1035. X            /* Copy the structure field by field. */
  1036. X            set_blk.sg_ispeed = initial_blk.sg_ispeed;
  1037. X            set_blk.sg_ospeed = initial_blk.sg_ospeed;
  1038. X            set_blk.sg_erase = initial_blk.sg_erase;
  1039. X            set_blk.sg_kill = initial_blk.sg_kill;
  1040. X            set_blk.sg_flags = initial_blk.sg_flags;
  1041. X#endif /* STRUCT_ASST */
  1042. X
  1043. X            /* And now set up the set_blk. */
  1044. X            erase = set_blk.sg_erase;
  1045. X
  1046. X            /* Go into CBREAK mode or stay that way if we are already. */
  1047. X            set_blk.sg_flags |= CBREAK;
  1048. X
  1049. X            /* Turn off echo. */
  1050. X            set_blk.sg_flags &= ~ECHO;
  1051. X#endif /* Sysv */
  1052. X            break;
  1053. X        }
  1054. X
  1055. X        case TERM_SET:{
  1056. X#ifdef Sysv
  1057. X            if (ioctl(0, TCSETA, (char *)&set_blk) == -1){
  1058. X                e_error("Could not ioctl stdin.");
  1059. X            }
  1060. X#else
  1061. X            if (ioctl(0, TIOCSETP, (char *)&set_blk) == -1){
  1062. X                e_error("Could not ioctl stdin.");
  1063. X            };
  1064. X#endif /* Sysv */
  1065. X            break;
  1066. X        }
  1067. X
  1068. X        case TERM_RESET:{
  1069. X#ifdef Sysv
  1070. X            if (ioctl(0, TCSETA, (char *)&initial_blk) == -1){
  1071. X                e_error("Could not ioctl stdin.");
  1072. X            }
  1073. X#else
  1074. X            if (ioctl(0, TIOCSETP, (char *)&initial_blk) == -1){
  1075. X                e_error("Could not ioctl stdin.");
  1076. X            }
  1077. X#endif /* Sysv */
  1078. X            break;
  1079. X        }
  1080. X
  1081. X        default:{
  1082. X            /* Look! - no ifdefs here. */
  1083. X            e_error("terminal() called with unknown parameter (%d).", what);
  1084. X        }
  1085. X    }
  1086. X    return;
  1087. X}
  1088. X
  1089. END_OF_FILE
  1090. if test 3469 -ne `wc -c <'terminal.c'`; then
  1091.     echo shar: \"'terminal.c'\" unpacked with wrong size!
  1092. fi
  1093. # end of 'terminal.c'
  1094. fi
  1095. echo shar: End of archive 2 \(of 3\).
  1096. cp /dev/null ark2isdone
  1097. MISSING=""
  1098. for I in 1 2 3 ; do
  1099.     if test ! -f ark${I}isdone ; then
  1100.     MISSING="${MISSING} ${I}"
  1101.     fi
  1102. done
  1103. if test "${MISSING}" = "" ; then
  1104.     echo You have unpacked all 3 archives.
  1105.     rm -f ark[1-9]isdone
  1106. else
  1107.     echo You still need to unpack the following archives:
  1108.     echo "        " ${MISSING}
  1109. fi
  1110. ##  End of shell archive.
  1111. exit 0
  1112.  
  1113.